﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace KnBinarySerializer
{
    internal class FormatterFactory2
    {
        public const byte CLASS_FORMATTER_KEY = (byte)0;
        static Dictionary<Type, IFormatter> typeDict;
        static Dictionary<byte, IFormatter> keyDict;
        static FormatterFactory2()
        {
            
            typeDict = new Dictionary<Type, IFormatter>();
            keyDict = new Dictionary<byte, IFormatter>();
            //添加所有Formatter
            Assembly asm = Assembly.GetExecutingAssembly();
            Type itype = typeof(IFormatter);
            foreach (Type type in asm.GetTypes())
            {
                if (!type.IsInterface && itype.IsAssignableFrom(type))
                {
                    IFormatter formatter = (IFormatter)Activator.CreateInstance(type);                    
                    byte key = formatter.GetKey();
                    if (keyDict.ContainsKey(key))
                        throw new Exception($"key[{key}]重复，添加{type.FullName}失败");
                    Type tp = formatter.GetHandleType();
                    if (tp != null)//类与列表类使用types标记，都返回null
                        typeDict.Add(formatter.GetHandleType(), formatter);
                    keyDict.Add(formatter.GetKey(), formatter);
                }
            }
        }
        //static IFormatter emptFormatter = new EmptyFormatter();
        public static IFormatter GetFormatter(object obj)
        {
            Type type = obj.GetType();
            return GetFormatter(type);
        }
        public static IFormatter GetFormatter(Type type) { 
            if (typeDict.ContainsKey(type))
                return (IFormatter)typeDict[type];

            if (typeof(Type).IsAssignableFrom(type))
                return keyDict[3];

            if (typeof(IDictionary).IsAssignableFrom(type))
                return keyDict[2];

            if (typeof(IEnumerable).IsAssignableFrom(type))
                return keyDict[1];
            else
                return keyDict[0];
        }
        public static IFormatter GetFormatter(byte key)
        {
            if (keyDict.ContainsKey(key))
                return (IFormatter)keyDict[key];
            else
                return null;
        }

        //public class EmptyFormatter : IFormatter
        //{
        //    public Type GetHandleType()
        //    {
        //        throw new NotImplementedException();
        //    }
        //}
    }
}
